<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>css点赞动画效果</title>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" 
  href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
  <!-- 第二步：css样式 -->
  <style>
    :root {
      --particle-color: #3049e9;
      --intervel: 30;
    }

    * {
      box-sizing: border-box;
    }

    body {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100%;
      height: 100vh;
    }
    body .canvas {
      padding-top: 75px;
      width: 75px;
      left: 75px;
    }
    body .canvas svg .hand {
      fill: none;
      stroke: #231f20;
      stroke-linecap: round;
      stroke-linejoin: round;
      stroke-width: 2px;
      transform-origin: left;
    }
    body .canvas svg .underline-section {
      background-color: #fff;
    }
    body .canvas svg .underline {
      stroke: #231f20;
      stroke-linecap: round;
      stroke-width: 2px;
      transform-origin: top;
    }
    body .canvas svg .under-particle {
      stroke: var(--particle-color);
      opacity: 0;
      stroke-width: 3px;
    }
    body .canvas svg #under-particle-1 {
      transform: rotate(20deg);
    }
    body .canvas svg #under-particle-3 {
      transform: rotate(-20deg);
    }
    body .canvas svg .upper-particle {
      transform-origin: center;
      transform: rotate(0deg);
    }
    body .canvas .particle-container {
      position: absolute;
      width: 150px;
      height: 150px;
      top: calc(50% - 25px);
      left: 50%;
      transform: translate(-50%, -50%) scale(1.5);
    }
    body .canvas .particle-container .upper-particle {
      opacity: 0;
    }
    body .canvas .particle-container .upper-particle-star {
      opacity: 0;
      stroke: #e9c030;
      stroke-width: 2.5px;
    }
    body .canvas .particle-container .upper-particle:nth-child(1) {
      stroke: #f07573;
      transform: rotate(calc(var(--intervel) * -3deg));
    }
    body .canvas .particle-container .upper-particle:nth-child(2) {
      stroke: #95f073;
      transform: rotate(calc(var(--intervel) * -2deg));
    }
    body .canvas .particle-container .upper-particle:nth-child(3) {
      stroke: #73f0bd;
      transform: rotate(calc(var(--intervel) * -1deg));
    }
    body .canvas .particle-container .upper-particle:nth-child(4) {
      stroke: #73c1f0;
      transform: rotate(calc(var(--intervel) * 0deg));
    }
    body .canvas .particle-container .upper-particle:nth-child(5) {
      stroke: #8b73f0;
      transform: rotate(calc(var(--intervel) * 1deg));
    }
    body .canvas .particle-container .upper-particle:nth-child(6) {
      stroke: #e773f0;
      transform: rotate(calc(var(--intervel) * 2deg));
    }
    body .canvas .particle-container .upper-particle:nth-child(7) {
      stroke: #f073a1;
      transform: rotate(calc(var(--intervel) * 3deg));
    }
  </style>
  </head>
<body>
<!-- 第一步：html布局 -->
<div class="canvas">
  <div class="hand-container">
    <svg class="hand-section" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
      <rect class="hand sleeve" x="5.68" y="12.41" width="6" height="14" rx="2" />
      <path class="hand" d="M11.68,14.41s3.2-1.63,3.2-6.29,4.67-2.48,
      4.67,3.26c0,2.26-1,2.29-1,2.29l5.68-.36a2,2,0,0,1,2.1,2.32l-1.39,
      8.29a2.06,2.06,0,0,1-2.05,1.72l-11.18-.13Z" />
    </svg>
  </div>
  <div class="underline-container">
    <svg class="underline-section" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
      <line x1="12" y1="2" x2="20" y2="2" class="underline" id="underline" />
      <line x1="12" y1="12" x2="12" y2="12" class="underline under-particle" 
      id="under-particle-1" />
      <line x1="16" y1="12" x2="16" y2="12" class="underline under-particle" 
      id="under-particle-2" />
      <line x1="20" y1="12" x2="20" y2="12" class="underline under-particle" 
      id="under-particle-3" />
    </svg>
  </div>
  <div class="particle-container">
    <svg class="particle-section" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
      <line x1="32" y1="10" x2="32" y2="14" class="underline upper-particle" />
      <line x1="32" y1="10" x2="32" y2="14" class="underline upper-particle" />
      <line x1="32" y1="10" x2="32" y2="14" class="underline upper-particle" />
      <line x1="32" y1="10" x2="32" y2="14" class="underline upper-particle" />
      <line x1="32" y1="10" x2="32" y2="14" class="underline upper-particle" />
      <line x1="32" y1="10" x2="32" y2="14" class="underline upper-particle" />
      <line x1="32" y1="10" x2="32" y2="14" class="underline upper-particle" />
      <line x1="40" y1="12" x2="40" y2="12" class="underline upper-particle-star" />
      <line x1="40" y1="16" x2="40" y2="16" class="underline upper-particle-star" />
      <line x1="38" y1="14" x2="38" y2="14" class="underline upper-particle-star" />
      <line x1="42" y1="14" x2="42" y2="14" class="underline upper-particle-star" />
    </svg>
  </div>
</div>
<!-- 第三步：js部分 -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js'>
  </script>
  <script>
    const root = document.querySelector(':root')
    const underParticle = document.querySelectorAll('.under-particle')
    const upperParticle = document.querySelectorAll('.upper-particle')
    const upperParticleStar = document.querySelectorAll('.upper-particle-star')

    let durationTime = 1000
    let loopCount = 3

    runAnimation()
    triggerLike()
    
    function triggerLike() {
      setTimeout(() => {
        anime({
          targets: 'svg.hand-section',
          keyframes: [
            { translateY: 0, rotate: 0, scale: 1 },
            { translateY: 18, rotate: 10, scale: 1},
            { translateY: -20, rotate: -10, scale: 1.2 },
            { translateY: -20, rotate: -10, scale: 1.2 },
            { translateY: -5, rotate: -5, scale: 1.0 }
          ],
          easing: 'easeInOutSine',
          duration: durationTime
        })
      
        anime({
          targets: document.getElementsByTagName("line")[0],
          keyframes: [
            { x1: 10, x2: 22 },
            { x1: 6, x2: 26 },
            { x1: 14, x2: 18 },
            { x1: 14, x2: 18 },
            { x1: 12, x2: 20 }
          ],
          easing: 'easeInOutSine',
          duration: durationTime
        })

        anime({
          targets: underParticle,
          keyframes: [
            { y1: 12, y2: 12, opacity: 0 },
            { y1: 12, y2: 16, opacity: 1 },
            { y1: 14, y2: 18, opacity: 1 },
            { y1: 14, y2: 18, opacity: 1 },
            { y1: 20, y2: 20, opacity: 0 }
          ],
          delay: 250,
          easing: 'easeInOutSine',
          duration: durationTime - 250
        })

        anime({
          targets: upperParticle,
          keyframes: [
            { y1: 12, y2: 16, opacity: 0 },
            { y1: 8, y2: 10, opacity: 1 },
            { y1: 8, y2: 12, opacity: 1 },
            { y1: 4, y2: 8, opacity: 1 },
            { y1: 4, y2: 4, opacity: 0 }
          ],
          delay: function(el, i) {
            return 250 + i * 25
          },
          easing: 'easeInOutSine',
          duration: durationTime
        })

        anime({
          targets: upperParticleStar,
          keyframes: [
            { opacity: 0 },
            { opacity: 1 },
            { opacity: 1 },
            { opacity: 1 },
            { opacity: 0 }
          ],
          delay: 250,
          easing: 'easeInOutSine',
          duration: durationTime - 250
        })

        anime({
          targets: upperParticleStar[0],
          y1: [12, 10],
          easing: 'easeInOutSine',
          duration: durationTime
        })

        anime({
          targets: upperParticleStar[1],
          y1: [16, 18],
          easing: 'easeInOutSine',
          duration: durationTime
        })

        anime({
          targets: upperParticleStar[2],
          x1: [38, 36],
          easing: 'easeInOutSine',
          duration: durationTime
        })

        anime({
          targets: upperParticleStar[3],
          x1: [42, 44],
          easing: 'easeInOutSine',
          duration: durationTime
        })
      }, durationTime * loopCount)
    }

    setInterval(() => {
      runAnimation()
      triggerLike()
    }, durationTime * (loopCount + 1))

    function runAnimation() {
      anime({
        targets: 'svg.hand-section',
        translateY: [-5, 0],
        rotate: [-5, 0],
        loop: loopCount,
        direction: 'alternate',
        easing: 'easeInOutSine',
        duration: durationTime
      })
      
      anime({
        targets: document.getElementsByTagName("line")[0],
        x1: [12, 10],
        x2: [20, 22],
        loop: loopCount,
        direction: 'alternate',
        easing: 'easeInOutSine',
        duration: durationTime
      })
    }
  </script>
</body>
</html>
